<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>雾化场景</title>
    <script src="js/three73.js"></script>
    <script src="js/Stats.js"></script>
    <script src="js/dat.gui.js"></script>
    <style>
        body{
            margin: 0;
            overflow: hidden;
        }
    </style>
</head>
<body>
<div id="WebGL-output"></div>
<div id="Stats-output"></div>

<script>
    window.onload = function(){
        var stats = initStats();//调用stat函数

        var scene = new THREE.Scene();  //定义场景

        //定义雾化,颜色，近处值，远处值，
        // 通过后面两个属性可以决定雾从什么时候开始，以及浓度加深的程度
        //还有另外一种方法可以设置场景中雾的浓度：scene.fog = new THREE.FogExp2(0xffffff,0.015);
        scene.fog = new THREE.Fog(0xffffff,0.015,100);

        var camera = new THREE.PerspectiveCamera(45,window.innerWidth/window.innerHeight,0.1,1000); //定义相机

        //定义渲染器
        var renderer = new THREE.WebGLRenderer();
        renderer.setClearColor(0xEEEEEE);
        renderer.setSize(window.innerWidth,window.innerHeight);
        //允许阴影映射：真，
        // 还需要明确定义哪些物体投射阴影，哪些物体接受阴影，
        // 以及定义哪个光源可以产生阴影
        renderer.shadowMap.enabled = true;

        //创建一个坐标轴对象并添加到场景中
        var axex = new THREE.AxisHelper(20);
        scene.add(axex);

        //创建一个聚光灯光源
        var spotLight = new THREE.SpotLight(0xffffff);
        spotLight.position.set(-40,60,-10);
        spotLight.castShadow = true;  //该光源能产生阴影
        scene.add(spotLight);
        //创建一个环境光源
        var ambientLight = new THREE.AmbientLight(0x0c0c0c);
        scene.add(ambientLight);



        //创建一个平面
        var planeGeometry = new THREE.PlaneGeometry(60,20,1,1);   //宽60，高20
        var planeMaterial = new THREE.MeshLambertMaterial({color:0xffffff});  //材质颜色
        var plane = new THREE.Mesh(planeGeometry,planeMaterial);   //合并在一个名叫plane的网格对象中

        //定义平面的位置
        plane.rotation.x = -0.5*Math.PI;

        plane.position.x = 15;
        plane.position.y = 0;
        plane.position.z = 0;

        plane.receiveShadow = true;//接受阴影

        scene.add(plane);

        var controls = new function(){
            this.rotationSpeed = 0.02;
            this.numberOfObjects = scene.children.length;
            this.cameraxxx = -30;
            this.camerayyy = 40;
            this.camerazzz = 30;

            this.addCube = function(){
                var cubeSize = Math.ceil((Math.random()*3));
                var cubeGeometry = new THREE.CubeGeometry(cubeSize,cubeSize,cubeSize);
                var cubeMaterial = new THREE.MeshLambertMaterial({color:Math.random()*0xffffff});
                var cube = new THREE.Mesh(cubeGeometry,cubeMaterial);
                cube.castShadow = true;

                //当前场景汇总对象的数量，如果使用Scene.getChildByName(name)函数，你可以直接获取指定的对象，然后执行一些操作
                cube.name = "cube-" + scene.children.length;

                //注意parameters不要少！
                cube.position.x = -30 + Math.round((Math.random()*planeGeometry.parameters.width));
                cube.position.y = Math.round((Math.random()*5));
                cube.position.z = -20+ Math.round((Math.random()*planeGeometry.parameters.height));
                scene.add(cube);
                this.numberOfObjects = scene.children.length;
            };

            //移除对象的时候还要检查一下这个对象是不是一个mesh对象，以防移除相机和光源
            this.removeCube = function(){
                var allChildren = scene.children;
                var lastObject = allChildren[allChildren.length-1];
                if(lastObject instanceof THREE.Mesh){
                    scene.remove(lastObject);
                    this.numberOfObjects = scene.children.length;
                }
            };

            //打印出场景的所有对象，并将结果输出到网络浏览器的console
            this.outputObjects = function(){
                console.log(scene.children);
            };

        };

        var gui = new dat.GUI();
        gui.add(controls, 'rotationSpeed', 0, 0.5);
        gui.add(controls, 'addCube');
        gui.add(controls, 'removeCube');
        gui.add(controls, 'outputObjects');
        gui.add(controls, 'numberOfObjects').listen();
        gui.add(controls,'cameraxxx',-100,100);
        gui.add(controls,'camerayyy',1,200);
        gui.add(controls,'camerazzz',1,200);

        camera.position.x = -30;
        camera.position.y = 40;
        camera.position.z = 30;
        camera.lookAt(scene.position);  //指向场景的中心

        //输出到页面
        document.getElementById('WebGL-output').appendChild(renderer.domElement);


        //在场景结束后调用一次函数来启动动画
        renderScene();

        function renderScene(){
            stats.update();       //实时更新

            scene.traverse(function(e){
                if(e instanceof THREE.Mesh && e != plane){
                    e.rotation.x += controls.rotationSpeed;
                    e.rotation.y += controls.rotationSpeed;
                    e.rotation.z += controls.rotationSpeed;
                }
            });
            camera.position.y = controls.camerayyy;
            camera.position.x = controls.cameraxxx;
            camera.position.z = controls.camerazzz;
            requestAnimationFrame(renderScene);
            renderer.render(scene,camera);
        }

        function initStats(){  //初始化函数，定义具体位置
            var stats = new Stats();
            stats.setMode(0);
            stats.domElement.style.position = 'absolute';
            stats.domElement.style.left = '0px';
            stats.domElement.style.top = '0px';
            document.getElementById('Stats-output').appendChild(stats.domElement);
            return stats;
        }

    }
</script>
</body>
</html>